#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/event_groups.h>
#include "esp_log.h"
#include "color_light.h"
//#include "light_driver.h"
#include "driver/rmt.h"
#include "led_strip.h"
#include "my_uart.h"

static const char *TAG = "color_light";

static const uint8_t  gamma[256] = {//ws2812颜色校准数组
     0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   1,   1,
     1,   1,   1,   1,   1,   1,   2,   2,   2,   2,   2,   3,   3,   3,   3,   4,
     4,   4,   4,   5,   5,   5,   5,   6,   6,   6,   7,   7,   7,   8,   8,   8,
     9,   9,  10,  10,  10,  11,  11,  12,  12,  12,  13,  13,  14,  14,  15,  15,
    16,  16,  17,  17,  18,  18,  19,  20,  20,  21,  21,  22,  22,  23,  24,  24,
    25,  25,  26,  27,  27,  28,  29,  29,  30,  31,  32,  32,  33,  34,  34,  35,
    36,  37,  37,  38,  39,  40,  41,  41,  42,  43,  44,  45,  45,  46,  47,  48,
    49,  50,  51,  52,  53,  53,  54,  55,  56,  57,  58,  59,  60,  61,  62,  63,
    64,  65,  66,  67,  68,  69,  70,  71,  72,  73,  74,  76,  77,  78,  79,  80,
    81,  82,  83,  84,  86,  87,  88,  89,  90,  92,  93,  94,  95,  96,  98,  99,
   100, 101, 103, 104, 105, 107, 108, 109, 110, 112, 113, 114, 116, 117, 118, 120,
   121, 123, 124, 125, 127, 128, 130, 131, 133, 134, 135, 137, 138, 140, 141, 143,
   144, 146, 147, 149, 150, 152, 153, 155, 157, 158, 160, 161, 163, 165, 166, 168,
   169, 171, 173, 174, 176, 178, 179, 181, 183, 184, 186, 188, 190, 191, 193, 195,
   197, 198, 200, 202, 204, 205, 207, 209, 211, 213, 214, 216, 218, 220, 222, 224,
   226, 228, 229, 231, 233, 235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255 };

static uint8_t ws2812_color_table[CONFIG_WS2812_LED_NUM*3];
static rmt_config_t config;
static led_strip_config_t strip_config;
static led_strip_t *strip = NULL;
EventGroupHandle_t s_led_perform_event_group = NULL;

led_attr_t led_ctrl;

static void esp_led_perform_task(void *arg);
uint8_t led_strip_init(void)
{
     config = (rmt_config_t)RMT_DEFAULT_CONFIG_TX(CONFIG_WS2812_GPIO_PIN, RMT_TX_CHANNEL);
    // set counter clock to 40MHz
    config.clk_div = 2;

    ESP_ERROR_CHECK(rmt_config(&config));
    ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));

    // install ws2812 driver
    strip_config = (led_strip_config_t)LED_STRIP_DEFAULT_CONFIG(CONFIG_WS2812_LED_NUM, (led_strip_dev_t)config.channel);
    strip = led_strip_new_rmt_ws2812(&strip_config);
    if (!strip) {
        ESP_LOGE(TAG, "install WS2812 driver failed");
    }
    // Clear LED strip (turn off all LEDs)
    ESP_ERROR_CHECK(strip->clear(strip, 100));
    //load font then convert
	//led_font_init();
    // Show simple rainbow chasing pattern
    ESP_LOGI(TAG, "LED Rainbow Chase Start");
    //create led_perform_task
    led_ctrl.mode = 4;
    xTaskCreatePinnedToCore(esp_led_perform_task, "local_led_perform_task", 3 * 1024, NULL, 1,NULL, 0);
    return 1;
}
void led_strip_hsv2rgb(uint32_t h, uint32_t s, uint32_t v, uint32_t *r, uint32_t *g, uint32_t *b)
{
    h %= 360; // h -> [0,360]
    uint32_t rgb_max = v * 2.55f;
    uint32_t rgb_min = rgb_max * (100 - s) / 100.0f;

    uint32_t i = h / 60;
    uint32_t diff = h % 60;

    // RGB adjustment amount by hue
    uint32_t rgb_adj = (rgb_max - rgb_min) * diff / 60;

    switch (i) {
    case 0:
        *r = rgb_max;
        *g = rgb_min + rgb_adj;
        *b = rgb_min;
        break;
    case 1:
        *r = rgb_max - rgb_adj;
        *g = rgb_max;
        *b = rgb_min;
        break;
    case 2:
        *r = rgb_min;
        *g = rgb_max;
        *b = rgb_min + rgb_adj;
        break;
    case 3:
        *r = rgb_min;
        *g = rgb_max - rgb_adj;
        *b = rgb_max;
        break;
    case 4:
        *r = rgb_min + rgb_adj;
        *g = rgb_min;
        *b = rgb_max;
        break;
    default:
        *r = rgb_max;
        *g = rgb_min;
        *b = rgb_max - rgb_adj;
        break;
    }
}
void led_strip_clear_all(void)
{
   uint16_t i = 0;

   for(i=0;i<CONFIG_WS2812_LED_NUM;i++){
	   ws2812_color_table[i*3] = 0x00;
	   ws2812_color_table[i*3+1] = 0x00;
	   ws2812_color_table[i*3+2] = 0x00;
   }
}
void led_strip_set_single(uint16_t index, uint8_t red, uint8_t green, uint8_t blue )
{
	if(index >= CONFIG_WS2812_LED_NUM){
		return;
	}
	ws2812_color_table[index*3] = red;
	ws2812_color_table[index*3+1] = green;
	ws2812_color_table[index*3+2] = blue;
}

void led_strip_set_color(uint16_t index, uint8_t red, uint8_t green, uint8_t blue )
{
    uint8_t i = 0;
	if(index>=CONFIG_WS2812_LED_NUM && index!=0xFF){
		return;
	}
    if(index < CONFIG_WS2812_LED_NUM){
        ws2812_color_table[index*3] = gamma[red];
        ws2812_color_table[index*3+1] = gamma[green];
        ws2812_color_table[index*3+2] = gamma[blue];
    }else{
        for(i=0;i<CONFIG_WS2812_LED_NUM;i++){
            ws2812_color_table[i*3] = gamma[red];
            ws2812_color_table[i*3+1] = gamma[green];
            ws2812_color_table[i*3+2] = gamma[blue];
        }
    }
}
void led_strip_set_num(uint16_t num)
{
    led_ctrl.led_num = num;
}
void led_strip_reset_pixel(led_strip_t *strip)
{
	ESP_ERROR_CHECK(strip->clear(strip,50));
}
void led_strip_colorwipe(led_strip_t *strip, uint32_t red, uint32_t green, uint32_t blue)
{
	int i=0;

    //led_strip_clear_all();
	//led_strip_reset_pixel(strip);
    for(i=0; i<CONFIG_WS2812_LED_NUM; i++){
		led_strip_set_color(i,red,green,blue);
		// Write RGB values to strip driver
		ESP_ERROR_CHECK(strip->set_pixel(strip, i, ws2812_color_table[i*3], ws2812_color_table[i*3+1], ws2812_color_table[i*3+2]));
		// Flush RGB values to LEDs
		ESP_ERROR_CHECK(strip->refresh(strip, 50));
		vTaskDelay(pdMS_TO_TICKS(55));
    }
}
void led_strip_breathe(void)
{
    int i=0;
    static uint8_t step = 0;
    static uint8_t red = 0;
    static uint8_t green = 0;
    static uint8_t blue = 0;
    static uint8_t rgb_dir = 0;

    switch(step)
    {
        case 0:
          red = 0;
          green = 0;
          blue = 0;
          led_strip_clear_all();
	      led_strip_reset_pixel(strip);
          step = 1;
          break;
        case 1:
          if(rgb_dir == 0){
              red++;
              if(red == 125){
                  rgb_dir = 1;
               }
          }else{
              if(red > 0){
                  red--;
              }
          }
          if(red == 0){
              rgb_dir = 0;
              step = 2;
          }
          break;
        case 2:
           if(rgb_dir == 0){
              green++;
              if(green == 125){
                  rgb_dir = 1;
               }
          }else{
              if(green > 0){
                  green--;
              }
          }
          if(green == 0){
              rgb_dir = 0;
              step = 3;
          }
           break;
        case 3:
           if(rgb_dir == 0){
              blue++;
              if(blue == 125){
                  rgb_dir = 1;
               }
          }else{
              if(blue > 0){
                  blue--;
              }
          }
          if(blue == 0){
              rgb_dir = 0;
              step = 4;
          }
           break;
        case 4:
           step = 0;
           break;
    }
    led_strip_set_color(0xFF,red,green,blue);
    // Write RGB values to strip driver
    for(i=0;i<CONFIG_WS2812_LED_NUM;i++){
        ESP_ERROR_CHECK(strip->set_pixel(strip, i, ws2812_color_table[i*3], ws2812_color_table[i*3+1], ws2812_color_table[i*3+2]));
    }
    // Flush RGB values to LEDs
    ESP_ERROR_CHECK(strip->refresh(strip, 50));
    vTaskDelay(pdMS_TO_TICKS(10));
}
void led_strip_wonderful_color(void)
{
    uint8_t i = 0;
    uint8_t red = 0;
    uint8_t green = 0;
    uint8_t blue = 0;
    static uint8_t rgb_index = 0;
    uint32_t color_table[18] = {0xF0F8FF,0x9966CC,0xFAEBD7,0x00FFFF,0x7FFFD4,0xF0FFFF,0xFF8C00,0x9932CC,0x8B0000,0xE9967A,0x8FBC8F,0x483D8B,0x0000FF,0x8A2BE2,0xA52A2A,0xDEB887,0x5F9EA0,0x7FFF00};

    red = (uint8_t)((color_table[rgb_index]>>16)&0xFF);
    green = (uint8_t)((color_table[rgb_index]>>8)&0xFF);
    blue = (uint8_t)((color_table[rgb_index]>>0)&0xFF);
    led_strip_set_color(0xFF,red,green,blue);
    // Write RGB values to strip driver
    for(i=0;i<CONFIG_WS2812_LED_NUM;i++){
        ESP_ERROR_CHECK(strip->set_pixel(strip, i, ws2812_color_table[i*3], ws2812_color_table[i*3+1], ws2812_color_table[i*3+2]));
    }
    // Flush RGB values to LEDs
    ESP_ERROR_CHECK(strip->refresh(strip, 50));
    vTaskDelay(pdMS_TO_TICKS(1500));
    rgb_index++;
    if(rgb_index >= 18){
        rgb_index = 0;
    }
}
void led_strip_follow_screen(void)
{
    uint8_t i = 0;
    // Write RGB values to strip driver
    if(uart_frame_get_state()==true){
        uart_frame_set_state(false);
        for(i=0;i<CONFIG_WS2812_LED_NUM;i++){
            ESP_ERROR_CHECK(strip->set_pixel(strip, i, ws2812_color_table[i*3], ws2812_color_table[i*3+1], ws2812_color_table[i*3+2]));
        }
        // Flush RGB values to LEDs
        ESP_ERROR_CHECK(strip->refresh(strip, 50));
    }
}
void esp_led_refresh_dotmatrix(void)
{
     switch(led_ctrl.mode)
	 {
         case 1://流水灯
		 	led_strip_colorwipe(strip, 55, 0, 0);
            led_strip_colorwipe(strip, 0, 55, 0);
            led_strip_colorwipe(strip, 0, 0, 55);
		 	break;
		 case 2://呼吸灯
            led_strip_breathe();
		 	break;
		 case 3://幻彩灯
            led_strip_wonderful_color();
		 	break;
         case 4://跟随屏幕
            led_strip_follow_screen();
            break;
		 default:
		    break;
	 }
}
static void esp_led_perform_task(void *arg)
{
    EventBits_t evt_bits = 0;

	ESP_LOGI(TAG, "esp_led_perform_task start!!!");
	//s_led_perform_event_group = xEventGroupCreate();
	//xEventGroupSetBits(s_led_perform_event_group, 0x01);
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(20));
        esp_led_refresh_dotmatrix();
    }
}

